package ccm;

import ccm.common.*;
import ccm.communicate.common.Communicate;
import ccm.communicate.file.FileSaver;
import ccm.communicate.smctp.Smctp;
import ccm.component.image.AdvancedResizeableImageJPanel;
import ccm.component.image.ImageDecoder;
import ccm.component.image.ManualResizeableImageJPanel;
import ccm.component.input.InputTestJPanel;
import ccm.component.menu.MenuJPanel;
import ccm.component.oscilloscope.OscilloscopeDataManager;
import ccm.component.oscilloscope.OscilloscopeJPanel;
import ccm.component.oscilloscope.ScnsDataManager;
import ccm.component.output.OutputJPanel;
import ccm.component.override.JButton;
import ccm.component.override.JComboBox;
import ccm.component.override.JFrame;
import ccm.component.override.JLabel;
import ccm.component.override.JMenuItem;
import ccm.component.override.*;
import ccm.tools.GenerateFont;
import ccm.tools.GenerateImage;
import ccm.tools.ImageViewer;
import ccm.tools.Label.Label;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CCMonitor extends JFrame implements ActionListener, StatusChangeListener
{
    static
    {
        CCMConfigManager.setStringIfAbsent("ccm/CCMonitor/communicateClass","ccm.communicate.serial.Serial");
    }

    protected final JButton startJButton;
    protected final JButton loadJButton;
    protected final JButton cleanJButton;
    protected final OscilloscopeDataManager visualScopeDataManager;
    protected final OutputJPanel outputJPanel;
    protected final OscilloscopeJPanel oscilloscopeJPanel;
    protected final ManualResizeableImageJPanel imageJPanel;
    protected final InputTestJPanel inputTestJPanel;
    protected final ImageDecoder imageDecoder;
    protected final JMenuItem setCommunicateClassJMenuItem;
    protected final MenuJPanel menuJPanel;
    protected final FileSaver fileSaver;
    protected final Communicate communicate;
    protected final Smctp smctp;

    public CCMonitor() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException
    {
        super(true);
        setLayout(new BorderLayout());
        System.out.println("文本大小："+SystemParametersInfo.getLfMenuFontLfHeight());
        System.out.println("缩放系数："+SystemParametersInfo.getFontRate());

        JSplitPane jSplitPane1=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        add(jSplitPane1,BorderLayout.CENTER);
        jSplitPane1.setOneTouchExpandable(true);
        jSplitPane1.setDividerLocation(0.0f);
        imageJPanel=new AdvancedResizeableImageJPanel();
        //jSplitPane1.setLeftComponent(imageJPanel);
        inputTestJPanel=new InputTestJPanel();
        jSplitPane1.setLeftComponent(inputTestJPanel);
        imageDecoder=new ImageDecoder();
        imageDecoder.addReceiveImageListener(imageJPanel);

        JSplitPane jSplitPane2=new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        jSplitPane1.setRightComponent(jSplitPane2);
        jSplitPane2.setOneTouchExpandable(true);
        jSplitPane2.setDividerLocation(550);
        jSplitPane2.add(oscilloscopeJPanel=new OscilloscopeJPanel(visualScopeDataManager=new ScnsDataManager()));
        addWindowListener(oscilloscopeJPanel);
        addWindowStateListener(oscilloscopeJPanel);
        jSplitPane2.add(outputJPanel=new OutputJPanel());
        //add(inputJPanel=new MultipleInputJPanel(),BorderLayout.SOUTH);
        add(menuJPanel=new MenuJPanel(),BorderLayout.SOUTH);

        final JPanel leftJPanel=new JPanel();
        final JScrollPane jScrollPane=new JScrollPane(leftJPanel);
        jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        add(jScrollPane,BorderLayout.EAST);
        leftJPanel.setLayout(new VFlowLayout());
        {
            Class<?> aClass=null;
            try
            {
                aClass=Class.forName(CCMConfigManager.getString("ccm/CCMonitor/communicateClass"));
            }catch(ClassNotFoundException ignore)
            {
            }
            if(aClass==null)
            {
                CCMConfigManager.setString("ccm/CCMonitor/communicateClass","ccm.communicate.serial.Serial");
                aClass=ccm.communicate.serial.Serial.class;
            }
            communicate=(Communicate)aClass.getDeclaredConstructor().newInstance();
        }
        fileSaver=new FileSaver();
        smctp=new Smctp();
        smctp.setNext(communicate,0);

        smctp.addReceiveDataListener(outputJPanel,Smctp.CHANNEL_DEBUG);
        smctp.addReceiveDataListener(inputTestJPanel,Smctp.CHANNEL_DEBUG);
        smctp.addReceiveDataListener((ReceiveDataListener)visualScopeDataManager,Smctp.CHANNEL_VISUAL_SCOPE);
//        smctp.addReceiveDataListener(imageDecoder,Smctp.CHANNEL_IMAGE);
        smctp.addReceiveDataListener(menuJPanel,Smctp.CHANNEL_MENU);

        menuJPanel.addReceiveDataListener(smctp);
        inputTestJPanel.addReceiveDataListener(smctp);

        smctp.addStatusChangeListener(this);
        smctp.addStatusChangeListener(menuJPanel);
        smctp.addStatusChangeListener(fileSaver);
        communicate.addStatusChangeListener(this);
        communicate.addReceiveDataListener(fileSaver);


        JPanel operateJPanel=new JPanel();
        leftJPanel.add(operateJPanel);
        operateJPanel.setLayout(new VFlowLayout());
        operateJPanel.setBorder(new TitledBorder("操作"));

        startJButton=new JButton("开始");
        operateJPanel.add(startJButton);
        startJButton.addActionListener(this);

        loadJButton=new JButton("加载");
        operateJPanel.add(loadJButton);
        loadJButton.addActionListener(this);

        cleanJButton=new JButton("清空");
        operateJPanel.add(cleanJButton);
        cleanJButton.addActionListener(this);

        leftJPanel.add(communicate.getConfigJPanel());
        leftJPanel.add(fileSaver.getConfigJPanel());
        leftJPanel.add(smctp.getConfigJPanel());

        JPanel infoJPanel=new JPanel();
        leftJPanel.add(infoJPanel);
        infoJPanel.setLayout(new VFlowLayout());
        infoJPanel.setBorder(new TitledBorder("信息"));


        Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(()->setTitle(smctp.getCurrentConnect()),0,5,TimeUnit.SECONDS);
        setCommunicateClassJMenuItem=new JMenuItem("设置通信方式(重启有效)");
        setJMenu.add(setCommunicateClassJMenuItem);
        setCommunicateClassJMenuItem.addActionListener(this);
    }

    @Override
    public void restart()
    {
        smctp.stop();
        dispose();
        main();
    }

    public static void main()
    {
        main(new String[0]);
    }

    public static void main(String[] args)
    {
        try
        {
            if(args.length==0||args[0].equals("CCMonitor"))
            {
                new CCMonitor().setVisible(true);
            }
            else if(args[0].equals("Label"))
            {
                new Label();
            }
            else if(args[0].equals("GenerateImage"))
            {
                new GenerateImage();
            }
            else if(args[0].equals("GenerateFont"))
            {
                new GenerateFont();
            }
            else if(args[0].equals("ImageViewer"))
            {
                new ImageViewer();
            }
        }catch(Exception e)
        {
            JOptionPane.showMessageDialog(null,e.getMessage(),"启动失败",JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource().equals(startJButton))
        {
            if(communicate.isOpen())
            {
                communicate.stop();
            }
            else
            {
                clear();
                communicate.start();
            }
        }
        else if(e.getSource().equals(cleanJButton))
        {
            clear();
        }
        else if(e.getSource().equals(loadJButton))
        {
            communicate.stop();
            clear();
            JFileChooser jFileChooser=new JFileChooser(CCMConfigManager.getString("ccm/communicate/file/FileSaver/dir"));
            jFileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            jFileChooser.showDialog(new JLabel(),"选择");
            smctp.removeStatusChangeListener(fileSaver);
            smctp.removeStatusChangeListener(menuJPanel);
            smctp.removeReceiveDataListener(menuJPanel,Smctp.CHANNEL_MENU);
            smctp.start();
            (new Thread(()->
            {
                try
                {
                    smctp.receiveData(new ReceiveDataEvent(communicate,FileSaver.readAll(jFileChooser.getSelectedFile())));
                }catch(IOException ex)
                {
                    ex.printStackTrace();
                }
                smctp.addStatusChangeListener(fileSaver);
                smctp.addStatusChangeListener(menuJPanel);
                smctp.addReceiveDataListener(menuJPanel,Smctp.CHANNEL_MENU);
            })).start();
        }
        else if(e.getSource().equals(setCommunicateClassJMenuItem))
        {
            JDialog jDialog=new JDialog(this,"选择通信方式(重启有效)",true);
            JPanel jPanel=new JPanel();
            jPanel.setLayout(new FlowLayout());
            jDialog.setContentPane(jPanel);
            final JComboBox<String> stringJComboBox=new JComboBox<String>(new String[]{"ccm.communicate.serial.Serial","ccm.communicate.tcp.TcpServer",});
            jPanel.add(stringJComboBox);
            stringJComboBox.setSelectedItem(CCMConfigManager.getString("ccm/CCMonitor/communicateClass"));
            jDialog.setSize(300,150);
            Point lu=getLocationOnScreen();
            Dimension ps=getSize();
            Dimension ms=jDialog.getSize();
            final JButton jButton1=new JButton("确定");
            jPanel.add(jButton1);
            jButton1.addActionListener(e1->
            {
                CCMConfigManager.setString("ccm/CCMonitor/communicateClass",(String)stringJComboBox.getSelectedItem());
                CCMConfigManager.save();
            });

            final JButton jButton2=new JButton("确定并重启");
            jPanel.add(jButton2);
            jButton2.addActionListener(e12->
            {
                CCMConfigManager.setString("ccm/CCMonitor/communicateClass",(String)stringJComboBox.getSelectedItem());
                CCMConfigManager.save();
                restart();
            });
            jDialog.setLocation((ps.width>ms.width)?(((ps.width-ms.width)/2)+lu.x):(lu.x),(ps.height>ms.height)?(((ps.height-ms.height)/2)+lu.y):(lu.y));
            jDialog.setVisible(true);
        }
    }

    protected void clear()
    {
        outputJPanel.clear();
        visualScopeDataManager.clear();
        imageDecoder.clear();
        menuJPanel.clear();
        oscilloscopeJPanel.enableAutoBiasAndResize(true);
    }


    public void statusChange(StatusChangeEvent e)
    {
        if(e.getReason()==StatusChangeEvent.START||e.getReason()==StatusChangeEvent.STOP)
        {
            if(e.getSource().equals(communicate))
            {
                startJButton.setText(communicate.isOpen()?"停止":"开始");
            }
            if(e.getSource().equals(smctp))
            {
                if(smctp.isOpen())
                {
                    clear();
                }
            }
        }
        setTitle(smctp.getCurrentConnect());
    }
}
